home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / hoster / hoster.c next >
C/C++ Source or Header  |  1997-08-08  |  20KB  |  926 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: hoster.c,v 1.4 1997/07/02 17:53:09 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  * hoster.c
  35.  *
  36.  * Example hoster task to demonstrate and verify the protocol.
  37.  * This code was cut out of the pvmd default hoster in startup.c,
  38.  * and minimally modified to make it compile here.
  39.  *
  40.  * 24 Jan 1994  Manchek
  41.  */
  42.  
  43. #ifdef HASSTDLIB
  44. #include <stdlib.h>
  45. #endif
  46. #include <stdio.h>
  47. #include <sys/types.h>
  48. #include <errno.h>
  49. #ifndef WIN32
  50. #include <pwd.h>
  51. #include <netdb.h>
  52. #endif
  53. #if defined(IMA_RS6K) || defined(IMA_SP2MPI)
  54. #include <sys/select.h>
  55. #endif
  56. #ifdef    SYSVSTR
  57. #include <string.h>
  58. #define    CINDEX(s,c)    strchr(s,c)
  59. #else
  60. #include <strings.h>
  61. #define    CINDEX(s,c)    index(s,c)
  62. #endif
  63. #include <pvm3.h>
  64. #include <pvmproto.h>
  65.  
  66. #ifdef WIN32
  67. #include "pvmwin.h"
  68. #endif
  69.  
  70. #ifndef    RSHCOMMAND
  71. #define    RSHCOMMAND    "/usr/ucb/rsh"
  72. #endif
  73.  
  74. #ifndef    RSHTIMEOUT
  75. #define    RSHTIMEOUT 100
  76. #endif
  77.  
  78. /* if > 1, uses parallel startup strategy */
  79. #ifndef    RSHNPLL
  80. #define    RSHNPLL    5
  81. #endif
  82.  
  83. #ifndef    max
  84. #define    max(a,b)    ((a)>(b)?(a):(b))
  85. #endif
  86.  
  87. #ifndef    min
  88. #define    min(a,b)    ((a)<(b)?(a):(b))
  89. #endif
  90.  
  91. #ifdef WIN32
  92. #define close(fd)    _close(fd)
  93. #endif
  94.  
  95. #define    TALLOC(n,t,g)    (t*)malloc((n)*sizeof(t))
  96. #define    FREE(p)    free((char *)p)
  97. #define    STRALLOC(s)            strcpy(TALLOC(strlen(s)+1,char,"str"),s)
  98.  
  99. #define    LISTPUTAFTER(o,n,f,r) \
  100.     { (n)->f=(o)->f; (n)->r=(o); (o)->f->r=(n); (o)->f=(n); }
  101. #define    LISTPUTBEFORE(o,n,f,r) \
  102.     { (n)->r=(o)->r; (n)->f=(o); (o)->r->f=(n); (o)->r=(n); }
  103. #define    LISTDELETE(e,f,r) \
  104.     { (e)->f->r=(e)->r; (e)->r->f=(e)->f; (e)->r=(e)->f=0; }
  105.  
  106. #define    TVCLEAR(tvp)    ((tvp)->tv_sec = (tvp)->tv_usec = 0)
  107.  
  108. #define    TVISSET(tvp)    ((tvp)->tv_sec || (tvp)->tv_usec)
  109.  
  110. #define    TVXLTY(xtv, ytv) \
  111.     ((xtv)->tv_sec < (ytv)->tv_sec || \
  112.         ((xtv)->tv_sec == (ytv)->tv_sec && (xtv)->tv_usec < (ytv)->tv_usec))
  113.  
  114. #define    TVXADDY(ztv, xtv, ytv)    \
  115.     if (((ztv)->tv_usec = (xtv)->tv_usec + (ytv)->tv_usec) < 1000000) {    \
  116.         (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec;    \
  117.     } else {    \
  118.         (ztv)->tv_usec -= 1000000;    \
  119.         (ztv)->tv_sec = (xtv)->tv_sec + (ytv)->tv_sec + 1;    \
  120.     }
  121.  
  122. #define    TVXSUBY(ztv, xtv, ytv)    \
  123.     if ((xtv)->tv_usec >= (ytv)->tv_usec) {    \
  124.         (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec;    \
  125.         (ztv)->tv_usec = (xtv)->tv_usec - (ytv)->tv_usec;    \
  126.     } else {    \
  127.         (ztv)->tv_sec = (xtv)->tv_sec - (ytv)->tv_sec - 1;    \
  128.         (ztv)->tv_usec = (xtv)->tv_usec + 1000000 - (ytv)->tv_usec;    \
  129.     }
  130.  
  131. /*
  132. *    for keeping state assoc. with a host
  133. */
  134.  
  135. struct hst {
  136.     int h_tid;
  137.     char *h_name;
  138.     char *h_login;
  139.     char *h_sopts;
  140.     int h_flag;
  141. #define    HST_PASSWORD    1        /* ask for a password */
  142. #define    HST_MANUAL        2        /* do manual startup */
  143.     char *h_cmd;
  144.     char *h_result;
  145. };
  146.  
  147. struct slot {
  148.     struct slot *s_link, *s_rlink;        /* free/active list */
  149.     struct hst *s_hst;                    /* host table entry */
  150.     struct timeval s_bail;                /* timeout time */
  151.     int s_rfd, s_wfd, s_efd;            /* slave stdin/out/err */
  152.     char s_buf[256];                    /* stdout from host */
  153.     char s_ebuf[256];                    /* stderr from host */
  154.     int s_len;                            /* length of s_buf */
  155.     int s_elen;                            /* length of s_ebuf */
  156. };
  157.  
  158.  
  159. /***************
  160.  **  Globals  **
  161.  **           **
  162.  ***************/
  163.  
  164. #ifndef HASERRORVARS
  165. extern int errno;
  166. #endif
  167.  
  168. int debugmask = 0;
  169.  
  170. #ifndef WIN32
  171. char *username = 0;
  172. #else
  173. extern char* username;
  174. #endif
  175.  
  176. char *getenv();
  177.  
  178. /***************
  179.  **  Private  **
  180.  **           **
  181.  ***************/
  182.  
  183. static struct slot slots[RSHNPLL+2];    /* state var/ctx each slot */
  184. static struct slot *slfree = 0;            /* free list of slots */
  185.  
  186.  
  187. int
  188. main(argc, argv)
  189.     int argc;
  190.     char **argv;
  191. {
  192. #ifdef WIN32 
  193.     static int init = 0;
  194.     static int needed = 1;
  195. #else
  196.     struct passwd *pe;
  197.     int uid;
  198.  
  199.     if ((uid = getuid()) == -1) {
  200.         fprintf(stderr, "main() can't getuid()\n");
  201.         exit(1);
  202.     }
  203.     if (pe = getpwuid(uid))
  204.         username = STRALLOC(pe->pw_name);
  205.     else
  206.         fprintf(stderr, "main() can't getpwuid\n");
  207.     endpwent();
  208. #endif
  209.  
  210.     pvm_mytid();
  211.     pvm_reg_hoster();
  212.     pvm_setopt(PvmResvTids, 1);
  213.  
  214. #ifndef WIN32
  215.     printf("*** PVM pvmd starter ***\n");
  216. #endif
  217.  
  218.     while (pvm_recv(-1, SM_STHOST) > 0) {
  219.  
  220. #ifdef WIN32
  221.         AllocConsole();
  222.         
  223.         GetStdHandle(STD_OUTPUT_HANDLE);
  224.         if (init)  
  225.             printf(
  226.                 "***need more ?                                 ***\n");
  227. #endif
  228.  
  229.         hoster();
  230.  
  231. #ifdef WIN32
  232.         if (!init) {
  233.             printf(
  234.                 "*** PVM pvmd starter                           ***\n");
  235.             printf(
  236.                 "*** Here you can see what your 'add command'   ***\n");
  237.             printf(
  238.                 "*** is doing.  Also, if you are required to    ***\n");
  239.             printf(
  240.                 "*** type in passwords :-( this is the right    ***\n");
  241.             printf(
  242.                 "*** place :-)                                  ***\n");
  243.             printf(
  244.                 "*** It will pop up the next time you have to   ***\n");
  245.             printf(
  246.                 "*** add more slaves and will vanish therefore. ***\n");
  247.             Sleep(12000);    
  248.             printf(
  249.                 "*** Now ! ..... later ...                      ***\n");
  250.             Sleep(1000);
  251.             FreeConsole();
  252.             init=1;
  253.         }
  254.     
  255.         FreeConsole();    
  256. #endif 
  257.     }
  258.  
  259.     pvm_exit();
  260.     exit(0);
  261.  
  262. #ifdef WIN32
  263.     return(0);
  264. #endif
  265. }
  266.  
  267.  
  268. /*    hoster()
  269. *
  270. *    Unpack host table from message, attempt to start 'em up,
  271. *    send reply message.
  272. */
  273.  
  274. hoster()
  275. {
  276.     int num;
  277.     int i;
  278.     struct hst **hostlist;
  279.     struct hst *hp;
  280.     char *p;
  281.     char sopts[64];
  282.     char lognam[256];
  283.     char cmd[512];
  284.     int fromtid;
  285.     int wid;
  286.     struct pvmminfo minfo;
  287.  
  288.     /*
  289.     * unpack the startup message
  290.     */
  291.  
  292.     pvm_bufinfo(pvm_getrbuf(), (int *)0, (int *)0, &fromtid);
  293.     pvm_unpackf("%d", &num);
  294.     pvm_getminfo(pvm_getrbuf(), &minfo);
  295.     wid = minfo.wid;
  296.     printf("hoster() %d to start, wait id %d\n", num, wid);
  297.     if (num > 0) {
  298.         hostlist = TALLOC(num, struct hst *, "xxx");
  299.         for (i = 0; i < num; i++) {
  300.             hp = TALLOC(1, struct hst, "xxx");
  301.             hostlist[i] = hp;
  302.             hp->h_flag = 0;
  303.             hp->h_result = 0;
  304.             if (pvm_unpackf("%d %s %s %s", &hp->h_tid, sopts, lognam, cmd)) {
  305.                 printf("hoster() bad message format\n");
  306.                 pvm_exit();
  307.                 exit(1);
  308.             }
  309.             hp->h_sopts = STRALLOC(sopts);
  310.             hp->h_login = STRALLOC(lognam);
  311.             hp->h_cmd = STRALLOC(cmd);
  312.             printf("%d. t%x %s so=\"%s\"\n", i,
  313.                     hp->h_tid,
  314.                     hp->h_login,
  315.                     hp->h_sopts);
  316.             if (p = CINDEX(hp->h_login, '@')) {
  317.                 hp->h_name = STRALLOC(p + 1);
  318.                 *p = 0;
  319.                 p = STRALLOC(hp->h_login);
  320.                 FREE(hp->h_login);
  321.                 hp->h_login = p;
  322.  
  323.             } else {
  324.                 hp->h_name = hp->h_login;
  325.                 hp->h_login = 0;
  326.             }
  327.             if (!strcmp(hp->h_sopts, "pw"))
  328.                 hp->h_flag |= HST_PASSWORD;
  329.             if (!strcmp(hp->h_sopts, "ms"))
  330.                 hp->h_flag |= HST_MANUAL;
  331.         }
  332.     }
  333.  
  334.     /*
  335.     * do it
  336.     */
  337.  
  338.     pl_startup(num, hostlist);
  339.  
  340.     /*
  341.     * send results back to pvmd
  342.     */
  343.  
  344.     pvm_packf("%+ %d", PvmDataFoo, num);
  345.     for (i = 0; i < num; i++) {
  346.         pvm_packf("%d", hostlist[i]->h_tid);
  347.         pvm_packf("%s", hostlist[i]->h_result
  348.                 ? hostlist[i]->h_result : "PvmDSysErr");
  349.     }
  350.  
  351. /*
  352.     printf("hoster() sending back host table\n");
  353. */
  354.     pvm_getminfo(pvm_getsbuf(), &minfo);
  355.     minfo.wid = wid;
  356.     pvm_setminfo(pvm_getsbuf(), &minfo);
  357.     pvm_send(fromtid, SM_STHOSTACK);
  358.  
  359.     return 0;
  360. }
  361.  
  362.  
  363. close_slot(sp)
  364.     struct slot *sp;
  365. {
  366.     if (sp->s_wfd != -1)
  367.         (void)close(sp->s_wfd);
  368.     if (sp->s_rfd != -1)
  369.         (void)close(sp->s_rfd);
  370.     if (sp->s_efd != -1)
  371.         (void)close(sp->s_efd);
  372.     LISTDELETE(sp, s_link, s_rlink);
  373.     LISTPUTBEFORE(slfree, sp, s_link, s_rlink);
  374.     return 0;
  375. }
  376.  
  377.  
  378. pl_startup(num, hostlist)
  379.     int num;
  380.     struct hst **hostlist;
  381. {
  382.     int nxth = 0;                        /* next host in list to start */
  383.     struct slot *slact = 0;                /* active list of slots */
  384.     struct hst *hp;
  385.     struct slot *sp, *sp2;
  386.     struct timeval tnow;
  387.     struct timeval tout;
  388. #ifdef IMA_OS2
  389.         fd_set rfds;
  390. #else
  391.     struct fd_set rfds;
  392. #endif
  393.     int nfds;
  394.     int i;
  395.     int n;
  396.     char *p;
  397.     char c;
  398.  
  399.     /* init slot free list */
  400.  
  401.     slfree = &slots[RSHNPLL+1];
  402.     slfree->s_link = slfree->s_rlink = slfree;
  403.     slact = &slots[RSHNPLL];
  404.     slact->s_link = slact->s_rlink = slact;
  405.     for (i = RSHNPLL; i-- > 0; ) {
  406.         LISTPUTAFTER(slfree, &slots[i], s_link, s_rlink);
  407.     }
  408.  
  409.     /*
  410.     * keep at this until all hosts in table are completed
  411.     */
  412.  
  413.     for (; ; ) {
  414.  
  415.         /*
  416.         * if empty slots, start on new hosts
  417.         */
  418.  
  419.         for (; ; ) {
  420.  
  421.             /* find a host for slot */
  422.  
  423.             if (slfree->s_link != slfree && nxth < num)
  424.                 hp = hostlist[nxth++];
  425.             else
  426.                 break;
  427.  
  428.             sp = slfree->s_link;
  429.             LISTDELETE(sp, s_link, s_rlink);
  430.             sp->s_hst = hp;
  431.             sp->s_len = 0;
  432.             sp->s_elen = 0;
  433.             if (debugmask) {
  434.                 fprintf(stderr, "pl_startup() trying %s\n", hp->h_name);
  435.             }
  436.             phase1(sp);
  437.             if (hp->h_result) {
  438.                 /* error or fully started (manual startup) */
  439.  
  440.                 LISTPUTBEFORE(slfree, sp, s_link, s_rlink);
  441.  
  442.             } else {
  443.                 /* partially started */
  444.  
  445.                 LISTPUTBEFORE(slact, sp, s_link, s_rlink);
  446.                 gettimeofday(&sp->s_bail, (struct timezone*)0);
  447.                 tout.tv_sec = RSHTIMEOUT;
  448.                 tout.tv_usec = 0;
  449.                 TVXADDY(&sp->s_bail, &sp->s_bail, &tout);
  450.             }
  451.         }
  452.  
  453.         /* if no hosts in progress, we are finished */
  454.  
  455.         if (slact->s_link == slact)
  456.             break;
  457.  
  458.         /*
  459.         * until next timeout, get output from any slot
  460.         */
  461.  
  462.         FD_ZERO(&rfds);
  463.         nfds = 0;
  464.         TVCLEAR(&tout);
  465.         gettimeofday(&tnow, (struct timezone*)0);
  466.         for (sp = slact->s_link; sp != slact; sp = sp->s_link) {
  467.             if (TVXLTY(&sp->s_bail, &tnow)) {
  468.                 fprintf(stderr,
  469.                     "pl_startup() giving up on host %s after %d secs\n",
  470.                         sp->s_hst->h_name, RSHTIMEOUT);
  471.                 sp->s_hst->h_result = STRALLOC("PvmCantStart");
  472.                 sp2 = sp->s_rlink;
  473.                 close_slot(sp);
  474.                 sp = sp2;
  475.                 continue;
  476.             }
  477.  
  478.             if (!TVISSET(&tout) || TVXLTY(&sp->s_bail, &tout))
  479.                 tout = sp->s_bail;
  480.             if (sp->s_rfd >= 0)
  481.                 FD_SET(sp->s_rfd, &rfds);
  482.             if (sp->s_rfd > nfds)
  483.                 nfds = sp->s_rfd;
  484.             if (sp->s_efd >= 0)
  485.                 FD_SET(sp->s_efd, &rfds);
  486.             if (sp->s_efd > nfds)
  487.                 nfds = sp->s_efd;
  488.         }
  489.  
  490.         if (slact->s_link == slact)
  491.             break;
  492.  
  493.         nfds++;
  494.  
  495.         if (TVXLTY(&tnow, &tout)) {
  496.             TVXSUBY(&tout, &tout, &tnow);
  497.         } else {
  498.             TVCLEAR(&tout);
  499.         }
  500.         if (debugmask) {
  501.             fprintf(stderr, "pl_startup() select timeout is %d.%06d\n",
  502.                     tout.tv_sec, tout.tv_usec);
  503.         }
  504.         if ((n = select(nfds, &rfds, (fd_set*)0, (fd_set*)0, &tout)) == -1) {
  505.             if (errno != EINTR) {
  506. #ifdef WIN32
  507.                 pvmlogperror("pl_startup() select");
  508. #else
  509.                 perror("pl_startup() select");
  510. #endif
  511.                 pvmbailout(0);
  512.             }
  513.         }
  514.         if (debugmask) {
  515.             fprintf(stderr, "pl_startup() select returns %d\n", n);
  516.         }
  517.         if (n < 1) {
  518.             if (n == -1 && errno != EINTR) {
  519. #ifdef WIN32
  520.                 pvmlogperror("pl_startup() select");
  521. #else
  522.                 perror("pl_startup() select");
  523. #endif
  524.                 pvmbailout(0);    /* XXX this is too harsh */
  525.             }
  526.             continue;
  527.         }
  528.  
  529.         /*
  530.         * check for response on stdout or stderr of any slave.
  531.         */
  532.  
  533.         for (sp = slact->s_link; sp != slact; sp = sp->s_link) {
  534.  
  535.             /*
  536.             * stderr ready.  log output with remote's host name.
  537.             */
  538.             if (sp->s_efd >= 0 && FD_ISSET(sp->s_efd, &rfds)) {
  539. #ifdef WIN32
  540.                 n = win32_read_socket(sp->s_efd,
  541.                         sp->s_ebuf + sp->s_elen,
  542.                         sizeof(sp->s_ebuf) - sp->s_elen - 1);
  543. #else
  544.                 n = read(sp->s_efd, sp->s_ebuf + sp->s_elen,
  545.                         sizeof(sp->s_ebuf) - sp->s_elen - 1);
  546. #endif
  547.                 if (n > 0) {
  548.                     sp->s_elen += n;
  549.                     sp->s_ebuf[sp->s_elen] = 0;
  550. #ifdef WIN32
  551.  
  552.                     p = sp->s_ebuf + sp->s_elen - n;
  553.                     fprintf(stderr, "stderr@%s: ", sp->s_hst->h_name);
  554.                     while (c = *p++ & 0x7f) {
  555.                         if (isprint(c))
  556.                             fputc(c, stderr);
  557.  
  558.                         else {
  559.                             fputc('^', stderr);
  560.                             fputc((c + '@') & 0x7f, stderr);
  561.                         }
  562.                     }
  563.                     fputc('\n', stderr);
  564. #else
  565.                     while (p = CINDEX(sp->s_ebuf, '\n')) {
  566.                         *p = 0;
  567.                         fprintf(stderr, "stderr@%s: %s\n",
  568.                                 sp->s_hst->h_name, sp->s_ebuf);
  569.                         p++;
  570.                         sp->s_elen -= p - sp->s_ebuf;
  571.                         if (sp->s_elen > 0) {
  572.                             bcopy(p, sp->s_ebuf, sp->s_elen);
  573.                             sp->s_ebuf[sp->s_elen] = 0;
  574.                         }
  575.                     }
  576.                     if (sp->s_elen == sizeof(sp->s_ebuf) - 1) {
  577.                         fprintf(stderr, "stderr@%s: %s\n",
  578.                                 sp->s_hst->h_name, sp->s_ebuf);
  579.                         sp->s_elen = 0;
  580.                     }
  581. #endif
  582.                 } else {
  583. #ifndef WIN32
  584.                     if (sp->s_elen > 0) {
  585.                         fprintf(stderr, "stderr@%s: %s\n",
  586.                                 sp->s_hst->h_name, sp->s_ebuf);
  587.                         sp->s_elen = 0;
  588.                     }
  589. #endif
  590.                     (void)close(sp->s_efd);
  591.                     sp->s_efd = -1;
  592.                 }
  593.             }
  594.  
  595.             /*
  596.             * stdout ready.
  597.             * look for a complete line starting with "ddpro".
  598.             */
  599.             if (sp->s_rfd >= 0 && FD_ISSET(sp->s_rfd, &rfds)) {
  600. #ifdef WIN32
  601.                 n = win32_read_socket(sp->s_rfd, sp->s_buf + sp->s_len,
  602.                         sizeof(sp->s_buf) - sp->s_len - 1);
  603. #else
  604.                 n = read(sp->s_rfd, sp->s_buf + sp->s_len,
  605.                         sizeof(sp->s_buf) - sp->s_len - 1);
  606. #endif
  607.                 if (n > 0) {
  608.                     sp->s_len += n;
  609. #ifdef WIN32
  610.                     if (sp->s_len >= sizeof(sp->s_buf)) {
  611.                         fprintf(stderr,
  612.                                 "pl_startup() pvmd@%s: big read\n",
  613.                                 sp->s_hst->h_name);
  614.                         sp->s_hst->h_result = STRALLOC("PvmCantStart");
  615.                     }
  616. #endif
  617.                     sp->s_buf[sp->s_len] = 0;
  618. #ifdef WIN32
  619.                     if (p = CINDEX(sp->s_buf + sp->s_len - n, '\n')) {
  620.                         if (debugmask) {
  621.                             fprintf(stderr, "pvmd@%s: %s",
  622.                                     sp->s_hst->h_name, sp->s_buf);
  623.                         }
  624.                         *p = 0;
  625.                         sp->s_hst->h_result = STRALLOC(sp->s_buf);
  626.                     }
  627. #else
  628.                     while (p = CINDEX(sp->s_buf, '\n')) {
  629.                         *p = 0;
  630.                         if (!strncmp(sp->s_buf, "ddpro", 5)) {
  631.                             if (debugmask) {
  632.                                 fprintf(stderr, "stdout@%s: %s\n",
  633.                                         sp->s_hst->h_name, sp->s_buf);
  634.                             }
  635.                             sp->s_hst->h_result = STRALLOC(sp->s_buf);
  636.                             break;
  637.  
  638.                         } else {
  639.                             fprintf(stderr, "stdout@%s: %s\n",
  640.                                     sp->s_hst->h_name, sp->s_buf);
  641.                             p++;
  642.                             sp->s_len -= p - sp->s_buf;
  643.                             if (sp->s_len > 0) {
  644.                                 bcopy(p, sp->s_buf, sp->s_len);
  645.                                 sp->s_buf[sp->s_len] = 0;
  646.                             }
  647.                         }
  648.                     }
  649.                     if (sp->s_len == sizeof(sp->s_buf) - 1) {
  650.                         fprintf(stderr, "stdout@%s: %s\n",
  651.                                 sp->s_hst->h_name, sp->s_buf);
  652.                         sp->s_len = 0;
  653.                     }
  654. #endif
  655.                 } else {
  656. #ifndef WIN32
  657.                     if (sp->s_len > 0) {
  658.                         fprintf(stderr, "stdout@%s: %s\n",
  659.                                 sp->s_hst->h_name, sp->s_buf);
  660.                         sp->s_len = 0;
  661.                     }
  662. #endif
  663.                     if (n) {
  664.                         fprintf(stderr, "pl_startup() stdout@%s\n",
  665.                                 sp->s_hst->h_name);
  666.                     } else {
  667.                         fprintf(stderr, "pl_startup() stdout@%s: EOF\n",
  668.                                 sp->s_hst->h_name);
  669.                     }
  670.                     sp->s_hst->h_result = STRALLOC("PvmCantStart");
  671. #ifndef WIN32
  672.                     if (sp->s_elen > 0) {
  673.                         fprintf(stderr, "stderr@%s: %s\n",
  674.                                 sp->s_hst->h_name, sp->s_ebuf);
  675.                         sp->s_elen = 0;
  676.                     }
  677. #endif
  678.                 }
  679.                 if (sp->s_hst->h_result) {
  680.                     sp2 = sp->s_rlink;
  681.                     close_slot(sp);
  682.                     sp = sp2;
  683.                     continue;
  684.                 }
  685.             }
  686.         }
  687.     }
  688.     return 0;
  689. }
  690.  
  691.  
  692.  
  693. phase1(sp)
  694.     struct slot *sp;
  695. {
  696.     struct hst *hp;
  697.     char *hn;
  698.     char *av[16];            /* for rsh args */
  699.     int ac;
  700.     char buf[512];
  701.     int pid = -1;            /* pid of rsh */
  702.     char *p;
  703.  
  704. #ifdef WIN32
  705.     char do_cmd[128];
  706.     char *val=0;
  707.     FILE   *faked_stream;
  708. #endif
  709.  
  710. #ifndef NOREXEC
  711.     struct servent *se;
  712.     static u_short execport = 0;
  713.  
  714.     if (!execport) {
  715.         if (!(se = getservbyname("exec", "tcp"))) {
  716.             fprintf(stderr, "phase1() can't getservbyname(): %s\n", "exec");
  717.             pvmbailout(0);
  718.         }
  719.         execport = se->s_port;
  720. #ifndef WIN32
  721.         endservent();
  722. #endif
  723.     }
  724. #endif
  725.  
  726.     hp = sp->s_hst;
  727.     hn = hp->h_name;
  728.     sp->s_rfd = sp->s_wfd = sp->s_efd = -1;
  729.  
  730.     /*
  731.     * XXX manual startup hack... this is if we can't use rexec or rsh
  732.     */
  733.  
  734.     if (hp->h_flag & HST_MANUAL) {
  735.         fprintf(stderr, "*** Manual startup ***\n");
  736.         fprintf(stderr, "Login to \"%s\" and type:\n", hn);
  737.         fprintf(stderr, "%s\n", hp->h_cmd);
  738.  
  739.     /* get version */
  740.  
  741.         fprintf(stderr, "Type response: ");
  742.         fflush(stderr);
  743.         if (!(fgets(buf, sizeof(buf), stdin))) {
  744.             fprintf(stderr, "host %s read error\n", hn);
  745.             goto oops;
  746.         }
  747.         p = buf + strlen(buf) - 1;
  748.         if (*p == '\n')
  749.             *p = 0;
  750.         hp->h_result = STRALLOC(buf);
  751.         fprintf(stderr, "Thanks\n");
  752.         fflush(stderr);
  753.         return 0;
  754.     }
  755.  
  756.     /*
  757.     * XXX end manual startup hack
  758.     */
  759.  
  760.     if (!(hp->h_flag & HST_PASSWORD)) {        /* use rsh to start */
  761.         int wpfd[2], rpfd[2], epfd[2];
  762.         int i;
  763.  
  764.         if (debugmask) {
  765.             fprintf(stderr, "phase1() trying rsh to %s\n", hn);
  766.         }
  767.  
  768.     /* fork an rsh to startup the slave pvmd */
  769.  
  770. #ifdef    IMA_TITN
  771.         if (socketpair(AF_UNIX, SOCK_STREAM, 0, wpfd) == -1
  772.         || socketpair(AF_UNIX, SOCK_STREAM, 0, rpfd) == -1
  773.         || socketpair(AF_UNIX, SOCK_STREAM, 0, epfd) == -1) {
  774.             perror("phase1() socketpair");
  775.             goto oops;
  776.         }
  777. #else
  778. #ifndef WIN32
  779.         if (pipe(wpfd) == -1 || pipe(rpfd) == -1 || pipe(epfd) == -1) {
  780.             perror("phase1() pipe");
  781.             goto oops;
  782.         }
  783. #endif
  784. #endif
  785.  
  786.         if (debugmask) {
  787.             fprintf(stderr, "phase1() pipes: %d %d %d %d %d %d\n",
  788.                     wpfd[0], wpfd[1], rpfd[0], rpfd[1], epfd[0], epfd[1]);
  789.         }
  790. #ifndef WIN32
  791.         if ((pid = fork()) == -1) {
  792.             perror("phase1() fork");
  793.             pvmbailout(0);
  794.         }
  795.         if (!pid) {
  796.             (void)dup2(wpfd[0], 0);
  797.             (void)dup2(rpfd[1], 1);
  798.             (void)dup2(epfd[1], 2);
  799.             for (i = getdtablesize(); --i > 2; )
  800.                 (void)close(i);
  801. #else
  802.         {
  803. #endif
  804.             ac = 0;
  805. #ifdef WIN32
  806.             if (getenv("PVM_RSH"))    /* do we have a setting for rsh ?*/
  807.                 av[ac++] = getenv("PVM_RSH");
  808.             else 
  809. #endif
  810.                 av[ac++] = RSHCOMMAND;
  811.             av[ac++] = hn;
  812.             if (hp->h_login) {
  813.                 av[ac++] = "-l";
  814.                 av[ac++] = hp->h_login;
  815.             }
  816. #ifdef WIN32
  817.             else {
  818.                 hp->h_login=username;
  819.                 av[ac++] = "-l";
  820.                 av[ac++] = hp->h_login;
  821.             }
  822. #endif
  823.             av[ac++] = hp->h_cmd;
  824.             /* av[ac++] = "-u"; WIN32 */
  825.             /* av[ac++] = username; WIN32 */
  826.             av[ac++] = 0;
  827.             if (debugmask) {
  828.                 for (ac = 0; av[ac]; ac++)
  829.                     fprintf(stderr, "av[%d]=\"%s\" ", ac, av[ac]);
  830.                 fputc('\n', stderr);
  831.             }
  832. #ifndef WIN32
  833.             execvp(av[0], av);
  834.             fputs("phase1() execvp failed\n", stderr);
  835.             fflush(stderr);
  836.             _exit(1);
  837. #else
  838.             strcpy(do_cmd,av[0]);
  839.             for (ac = 1; av[ac]; ac++) {
  840.                     strcat(do_cmd," ");
  841.                     strcat(do_cmd,av[ac]);
  842.             }
  843.             faked_stream=_popen(do_cmd,"r"); 
  844.             
  845.             if (faked_stream != NULL)
  846.             {
  847.                 while (1) {
  848.                     fgets(buf,100,faked_stream);
  849.                     if (strstr(buf,"ddpro")) {
  850.                         if (!val)
  851.                             val = malloc(sizeof (buf) * sizeof(char));
  852.                         strcpy(val,buf);
  853.                         sp->s_hst->h_result=val;
  854.                         break;
  855.                         /* we got the message */
  856.                     }
  857.                     if (strcmp(buf,"PvmDupHost")){
  858.                         if (!val)
  859.                             val = malloc(sizeof (buf) * sizeof(char));
  860.                         strcpy(val,buf);
  861.                         sp->s_hst->h_result=val;
  862.                         break;
  863.                     }
  864.                 }
  865.             }        
  866.  
  867.             /* how can we close this ??? */
  868.             /* _pclose(faked_stream); */
  869. #endif
  870.         }
  871. #ifndef WIN32
  872.         (void)close(wpfd[0]);
  873.         (void)close(rpfd[1]);
  874.         (void)close(epfd[1]);
  875.         sp->s_wfd = wpfd[1];
  876.         sp->s_rfd = rpfd[0];
  877.         sp->s_efd = epfd[0];
  878. #endif
  879.     } else {        /* use rexec to start */
  880.  
  881. #ifdef NOREXEC
  882. #ifdef WIN32
  883.         fprintf(stderr, "slconfg() sorry, no rexec()\n");
  884. #else
  885.         fprintf(stderr, "slconfg() hoster was built without rexec support, can't take passwords\n");
  886. #endif
  887.         goto oops;
  888. #else
  889.         if (debugmask) {
  890.             fprintf(stderr, "phase1() rexec \"%s\"\n", hp->h_cmd);
  891.         }
  892. #ifndef WIN32
  893.         if ((sp->s_wfd = sp->s_rfd = rexec(&hn, execport,
  894.                 (hp->h_login ? hp->h_login : username),
  895.                 (char*)0, hp->h_cmd, &sp->s_efd))
  896.         == -1) {
  897.             fprintf(stderr, "phase1() rexec failed for host %s\n", hn);
  898.             goto oops;
  899.         }
  900. #else
  901.         sp->s_hst->h_result = malloc (512 * sizeof(char));
  902.  
  903.         if (!rexec(hn,(hp->h_login ? hp->h_login : username),
  904.                     hp->h_cmd,sp->s_hst->h_result))
  905.         {
  906.             fprintf(stderr, "phase1() rexec failed for host %s\n", hn);
  907.             goto oops;
  908.         }
  909. #endif
  910. #endif
  911.     }
  912.     return 0;
  913.  
  914. oops:
  915.     hp->h_result = STRALLOC("PvmCantStart");
  916.     if (sp->s_wfd != -1)
  917.         close(sp->s_wfd);
  918.     if (sp->s_rfd != -1)
  919.         close(sp->s_rfd);
  920.     if (sp->s_efd != -1)
  921.         close(sp->s_efd);
  922.     sp->s_wfd = sp->s_rfd = sp->s_efd = -1;
  923.     return 1;
  924. }
  925.  
  926.